package edu.cs.usask.ca.silver.api.businesslogic;

import java.util.Date;
import java.util.HashMap;

import edu.cs.usask.ca.silver.api.persistence.StorageI;
import edu.cs.usask.ca.silver.businesslogic.ids.FileID;
import edu.cs.usask.ca.silver.businesslogic.ids.GroupID;
import edu.cs.usask.ca.silver.businesslogic.ids.ModelProjectID;
import edu.cs.usask.ca.silver.businesslogic.ids.ModelVersionID;
import edu.cs.usask.ca.silver.definitions.SupportedModelType;

/**
 * 
 * This is the interface for the model project. It is the root of a simulation
 * project.
 * 
 * @author Daniel Funk
 * @author Yudi Xue
 */
public interface ModelProjectI {

	/**
	 * Creates a new model project in persistence layer. The creation date is
	 * set to current time. The Id in the persistence layer is a unique integer
	 * but will be converted to a ModelProjecID in the bean. This ID is unique
	 * across Silver. As part of creating a Model Project from a source file, a
	 * new version, scenario collection and scenario will be created, along with
	 * all the necessary parameters and a parameter set. The source file will
	 * also be added to the DB and set as the source file for the newly created
	 * version. The scenario that is created is set as original and baseline
	 * scenario for the version. Currently, this method also takes in the
	 * location of a jar file, which contains the compiled AnyLogic classes for
	 * this project.
	 * 
	 * @param parentGroup
	 *            TODO
	 * @param mpName
	 *            The name of the project
	 * @param mpCreator
	 *            The project creator
	 * @param mpDescr
	 *            Project description
	 * @param soureFileLocation
	 *            The location of the source file on the local disk
	 * @param storage TODO
	 * @param jarFileLocation
	 *            The location of the jar file containing the compiled AnyLogic
	 *            classes
	 * @return A unique ModelProject ID
	 * @throws Exception
	 */
	public ModelProjectID createGenericModelProjectWithSource(GroupID parentGroup,
			String mpName, String mpCreator, String mpDescr,
			String soureFileLocation, StorageI storage) throws Exception;
	
	public ModelProjectID createVensimModelProjectWithSource(GroupID parentGroup,
			String mpName, String mpCreator, String mpDescr,
			String soureFileLocation, StorageI storage) throws Exception, UnsatisfiedLinkError;

	/**
	 * Creates an "empty" Model Project without a source file. Use this method
	 * if you plan on adding versions from source files at a later time.
	 * 
	 * @param parentGroup
	 *            The group that the project belongs to.
	 * @param mpName
	 *            The project name
	 * @param mpCreator
	 *            Project creator
	 * @param mpDescr
	 *            Project description
	 * @param source TODO
	 * @param storage TODO
	 * @return A unique ModelProject ID
	 * @throws Exception
	 */
	public ModelProjectID createGenericModelProject(GroupID parentGroup,
			String mpName, String mpCreator, String mpDescr, String source, StorageI storage) throws Exception;
	
	
	public ModelProjectID createVensimModelProject(GroupID parentGroup,
			String mpName, String mpCreator, String mpDescr, String source, StorageI storage) throws Exception;

	/**
	 * Retrieves the unique ids of all ModelProjects managed by Silver
	 * @param storage TODO
	 * 
	 * @return Array of unique ModelProject ids
	 * @throws Exception
	 */
	public ModelProjectID[] getAllModelProjectIDs(StorageI storage) throws Exception;

	/**
	 * Returns a string containing the XML representation of the model project
	 * (non-recursive).
	 * 
	 * @param mpId
	 *            A unique ModelProject ID
	 * @param storage TODO
	 * @return String of XML representation of the model project
	 * @throws Exception
	 */
	public String getModelProjectAsXML(ModelProjectID mpId, StorageI storage) throws Exception;

	public String[] getModelProjectNamesByGroupID(GroupID gId, StorageI storage) throws Exception;

	/**
	 * Returns the name of a project as String
	 * 
	 * @param mpId
	 *            A unique ModelProject ID
	 * @param storage TODO
	 * @return The project name as String
	 * @throws Exception
	 */
	public String getName(ModelProjectID mpId, StorageI storage) throws Exception;

	/**
	 * Returns the type of a project as a String for example, it might be
	 * "ANYLOGIC" for Anylogic models or "VESIM" for Vensim models.
	 * 
	 * @param mpId
	 * @param storage TODO
	 * @return the type of associated model. Return "UNSPECIFIED TYPE" if the
	 *         type is not specified.
	 * @throws Exception
	 */
	public String getType(ModelProjectID mpId, StorageI storage) throws Exception;

	/**
	 * Returns the project description as String
	 * 
	 * @param mpId
	 *            A unique ModelProject ID
	 * @param storage TODO
	 * @return The project description as String
	 * @throws Exception
	 */
	public String getDescription(ModelProjectID mpId, StorageI storage) throws Exception;

	/**
	 * Returns the project creator as String
	 * 
	 * @param mpId
	 *            A unique ModelProject ID
	 * @param storage TODO
	 * @return The project Creator as String
	 * @throws Exception
	 */
	public String getCreator(ModelProjectID mpId, StorageI storage) throws Exception;

	/**
	 * Returns the date on which a project was created; to display time, use @getCreationTime
	 * method.
	 * @param mpId TODO
	 * @param storage
	 *            A unique ModelProject ID
	 * 
	 * @return The project creation date
	 * @throws Exception
	 */
	public Date getCreationDate(ModelProjectID mpId, StorageI storage) throws Exception;

	/**
	 * returns the time on which a project was created; to display creation
	 * date, use @getCreationDate
	 * 
	 * @param mpId
	 *            A unique ModelProjectID
	 * @param storage TODO
	 * @return The project creation time
	 * @throws Exception
	 */
	public Date getCreationTime(ModelProjectID mpId, StorageI storage) throws Exception;

	/**
	 * returns the owner group id for the current model project.
	 * 
	 * @param mpId
	 *            current model project id
	 * @param storage TODO
	 * @return GroupID parent group id
	 */
	public GroupID getParentGroupID(ModelProjectID mpId, StorageI storage) throws Exception;

	/**
	 * Returns an array of ModelVersionIDs, namely the IDs of all versions
	 * contained within this project.
	 * 
	 * @param mpId
	 *            A unique ModelProject ID
	 * @param storage TODO
	 * @return An array of all unique child ModelVersionIDs
	 * @throws Exception
	 */
	public ModelVersionID[] getModelVersionIds(ModelProjectID mpId, StorageI storage)
			throws Exception;

	/**
	 * Returns an array of FileIDs of all files associated with this model
	 * project
	 * 
	 * @param mpId
	 *            A unique ModelProjectID
	 * @param storage TODO
	 * @return Array of fileIDs of all file associated with this project
	 * @throws Exception
	 */
	public FileID[] getAssociatedFileIds(ModelProjectID mpId, StorageI storage) throws Exception;

	/**
	 * Returns a hashmap of ModelVersionIDs and the associated version names.
	 * The child versions of this model project.
	 * 
	 * (Currently Not implemented)
	 * 
	 * @param mpId
	 *            A unique ModelProject ID
	 * @param storage TODO
	 * @return A HashMap of Version IDs and Version names
	 * @throws Exception
	 */
	public HashMap<ModelVersionID, String> getModelVersions(ModelProjectID mpId, StorageI storage)
			throws Exception;

	/**
	 * Change the name of a project in the storage layer.
	 * 
	 * @param mpId
	 *            A unique ModelProject ID
	 * @param name
	 *            The (new) project name
	 * @param storage TODO
	 * @return TODO
	 * @throws Exception
	 */
	public boolean setName(ModelProjectID mpId, String name, StorageI storage) throws Exception;

	/**
	 * Allow to set the type of a project in the storage layer.
	 * 
	 * @param mpId
	 *            A unique ModelProject ID
	 * @param type
	 *            The (new) project id
	 * @param storage TODO
	 * @throws Exception
	 */
	public void setType(ModelProjectID mpId, String type, StorageI storage) throws Exception;

	/**
	 * Change the description of a project in the storage layer.
	 * 
	 * @param mpId
	 *            A unique ModelProject ID
	 * @param description
	 *            The (new) project description
	 * @param storage TODO
	 * @return TODO
	 * @throws Exception
	 */
	public boolean setDescription(ModelProjectID mpId, String description, StorageI storage)
			throws Exception;

	/**
	 * Remove a project from storage including all versions, scenarios, etc.
	 * 
	 * @param mpId
	 *            A unique ModelProject ID
	 * @param storage TODO
	 * @return TODO
	 * @throws Exception
	 */
	public boolean deleteProject(ModelProjectID mpId, StorageI storage) throws Exception;

	public ModelProjectID createModelProject(SupportedModelType supportedModelType,
			GroupID parentGroup, String mpName, String mpCreator,
			String mpDescr, String sourceFile, String classFile, StorageI storage) throws Exception;

	public ModelProjectID createAnylogicProject(GroupID parentGroup, String mpName,
			String mpCreator, String mpDescr, String sourceFile,
			String classFile, StorageI storage) throws Exception;

	public ModelProjectID createAnylogicProjectWithSource(GroupID parentGroup,
			String mpName, String mpCreator, String mpDescr, String sourceFile,
			String classFile, StorageI storage) throws Exception;

}
